#    Stingingnettlepy - A website generator for creating simple static websites.
#    Copyright (C) 2013  Jannik Haberbosch
#
#    This program is free software: you can redistribute it and/or modify
#    it under the terms of the GNU General Public License as published by
#    the Free Software Foundation, either version 3 of the License, or
#    (at your option) any later version.
#
#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU General Public License for more details.
#
#    You should have received a copy of the GNU General Public License
#    along with this program.  If not, see <http://www.gnu.org/licenses/>.


# Standard Python modules
import os
import os.path
import json
import re
import collections

# Project modules.
from stingingnettlepy.constants import constants
from stingingnettlepy import dict_functions
from stingingnettlepy.classes.Template import Template
from stingingnettlepy import navigation_functions
from stingingnettlepy.functions import template_functions


# The entry-point.
def main():
	"""Creates the page- and navigation containers for each single page of the
	website.
	They will be created in the "in/" directory of a website project.
	The containers for the navigation already contain the generated HTML-code
	that makes up the navigation for a single page.
	
	One can then edit the page containers to suit ones needs.  However, one should
	keep in mind that editing the navigation containers it not recommended
	unless one knows what one wants to do.

	"""
	# The site structure must be valid JSON.
	try:
		site_structure = json.load(
			open( constants.RELPATH_SITE_STRUCTURE ),
			object_pairs_hook = collections.OrderedDict
		)
	except ValueError as e:
		print( constants.ERR_MSG_LOAD_SITE_STRUCTURE %
			( constants.RELPATH_SITE_STRUCTURE, e )
		)
		return 0
	
	
	# The templates specified in the site structure must exist.
	# Fetch all templates that the user has defined in the 'website_structure'
	# file and store them in a list as strings.
	found_templates_in_site_structure = []
	keys = dict_functions.walk( site_structure )
	for key in keys:
		result = re.search( "template:[A-Za-z0-9_]*", key )
		if result is not None:
			# Add the name of the found template (remove the "template:" part)
			# But append a ".html" extension.
			found_templates_in_site_structure.append(
				result.group( 0 ).split( ":" )[1] + constants.EXT_HTML
			)
	# Now validate that the templates really do exist.
	templates_exist = True
	for template in found_templates_in_site_structure:
		if not os.path.exists(
			os.path.join( constants.RELPATH_TEMPLATES, template )
		):
			# A template does not exist.
			print( constants.MSG_ERR_TEMPLATE_DOES_NOT_EXIST % template )
			if templates_exist:
				templates_exist = False

	if templates_exist == False:
		# Abort creating the cpntainers.
		return False


	# Create instances that represent each of the templates.  For more
	# information about each of these instances, please take a look at the
	# class "Template".
	templates = load_templates()


	# Create the containers for our pages now.
	# Existing containers are not deleted nor re-created.
	# Non-existing containers are created.
	if not create_pages_and_containers( site_structure, templates, site_structure ):
		# There has been an error creating containers.
		return False


# TODO
def create_pages_and_containers( node, templates, complete_node, rootpath = constants.RELPATH_PAGES, page_id = 1 ):
	"""Creates pages and containers if either of them do not already exist.

	"""
	for key, value in node.items():
	
		# Create directories (pages)
		# We only need the name of the page.
		if key.find( ":" ) is -1:
			pagename = key.strip().replace( " ", "_" )
		else:
			pagename = key.split( "template:" )[0].strip().replace( " ", "_" )

		complete_rel_path = os.path.join( rootpath, pagename )
		if not os.path.exists( complete_rel_path ):
			try:
				os.makedirs( complete_rel_path )
			except ValueError as e:
				print( e )
				return False

		# Create files (containers)
		# Use the default template?
		result = re.search( "template:[A-Za-z0-9_]*", key )
		if result is None:
			# Use the default template.		
			template_name = constants.DEFAULT_TEMPLATE + constants.EXT_HTML
			template = get_template( templates, template_name )
		else:
			# Use another template.		
			template_name = result.group( 0 ).split( ":" )[1] + constants.EXT_HTML
			template = get_template( templates, template_name )
			
		containers = template.containers
		for container in containers:
			if not os.path.exists( os.path.join( rootpath, pagename, container[1:-1] ) ):
				open(
					os.path.join( rootpath, pagename, container[1:-1] ),
					"w"
				).close()


		# Create files (main-navigation containers )
		for main_navigation_container in template.main_navigation_containers:
			with open(
				os.path.join( rootpath, pagename, main_navigation_container.replace( "%", "" ) ),
				"w"
			) as f:
				# Generate the main navigation (html code) for this main
				# navigation container and put it in the file.

				# Create the html code.
				main_navigation_html = navigation_functions.create_main_navigation( complete_node )

				# And put it inside the created main navigation container (which is a file).
				f.write( main_navigation_html )

		# Create files (sub-navigation containers )
		part_of_root_path = rootpath[8:].replace( "\\", "/" )
		for sub_navigation_container in template.sub_navigation_containers:
			with open(
				os.path.join(
					rootpath, pagename, sub_navigation_container.replace( "%", "" )
				),
				"w"
			) as f:
				# Generate the sub navigation (html code) for this sub navigation
				# container and put it in the file.

				# Create the html code.
				HTML = ""
#				sub_navigation_html = navigation_functions.create_sub_navigation( complete_node, page_id, pagename, part_of_root_path )
				HTML = navigation_functions.create_sub_navigation2( complete_node, complete_rel_path[9:].replace( "\\", "/" ),
					complete_rel_path[9:].replace( "\\", "/" ), 0 )

				# And put it inside the created sub navigation container (which is a file ).
				f.write( HTML )


		page_id += 1
		
		if len( value ) > 0:
			page_id = create_pages_and_containers( value, templates, complete_node, complete_rel_path, page_id )

	return page_id


def load_templates():
	"""Creates 'Template' objects that represent templates and returns those
	as a list.
	
	Return values
		list()
			A list containg the 'Template' instances.

	"""
	templates = []
	for template_filename in os.listdir( constants.RELPATH_TEMPLATES ):
		templates.append(
			Template(
				os.path.join( constants.RELPATH_TEMPLATES, template_filename )
			)
		)
		
	return templates


def get_template( templates, template_name ):
	"""Returns a 'Template' instance of the 'templates' tuple whose 'name'
	property matches 'template_name'.
	
	If no suitable 'Template' instance has been found, 'None' is returned.
	
	"""
	for template in templates:
		if template.name == template_name:
			return template
			
	return None
